package org.example.util;

import com.google.common.collect.ImmutableList;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

/**
 * IP 工具类.
 *
 * @author Jjn
 * @since 2021-09-30 16:13
 */
@Slf4j
public class IpUtil {
    
    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST = "localhost";
    
    private static final List<String> IP_HEADER_CANDIDATES = ImmutableList.of(
            "X-Real-IP",
            "X-Forwarded-For",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR"
    );
    
    private IpUtil() {
    
    }
    
    public static int ipToInt(InetAddress ip) {
        byte[] octets = ip.getAddress();
        int result = 0;
        for (byte octet : octets) {
            result <<= 8;
            result |= octet & 0xff;
        }
        return result;
    }
    
    public static int ipToInt(String ip) throws UnknownHostException {
        return ipToInt(InetAddress.getByName(ip));
    }
    
    
    /**
     * 获取 IP地址
     * 使用 Nginx等反向代理软件， 则不能通过 request.getRemoteAddr()获取 IP地址
     * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，
     * X-Forwarded-For中第一个非 unknown的有效IP字符串，则为真实IP地址
     */
    public static String getIpAddress(HttpServletRequest request) {
        for (String header : IP_HEADER_CANDIDATES) {
            String ipList = request.getHeader(header);
            if (ipList != null && !ipList.isEmpty() && !UNKNOWN.equalsIgnoreCase(ipList)) {
                return ipList.split(",")[0];
            }
        }
        return "0:0:0:0:0:0:0:1".equals(request.getRemoteAddr()) ? LOCALHOST : request.getRemoteAddr();
    }
}
